# -*- coding: utf-8 -*-
"""
Created on Sat Nov  2 15:42:01 2019

@author: ADEJUNIOR
"""

# Library imports

import cv2
import numpy as np
import PySimpleGUI as sg
from PIL import Image
import math
import csv
import base64
from io import BytesIO
from skimage.segmentation import slic
from numba import jit
import time


#  View functions and definitions
SCREEN_SIZE = 500

menu_def = [['File', ['Open image', 'Open Superpixel', 'Generate Superpixels',
                      'Load CSV file', 'Save mask', 'Exit']],
            ['Help', ['About...', 'Reload']]]


layout = [[sg.Menu(menu_def, tearoff=True)],
          [sg.Button("process", size=(8, 4), key="process"),
           sg.Button("Move", size=(8, 4), key="drag"),
           sg.Button("Paint super pixel", size=(8, 4), key="brush"),
           sg.Button("Least path", size=(8, 4), key="path"),
           sg.Button("Region growing", size=(8, 4), key="grow"),
           sg.Button("Forest segment", size=(8, 4), key="forest"),
           sg.Button("Dynamic forest", size=(8, 4), key="dynamic")
           ],
          [sg.Graph(canvas_size=(SCREEN_SIZE, SCREEN_SIZE),
                    graph_bottom_left=(0, 0),
                    enable_events=True, drag_submits=True,
                    background_color='black',
                    graph_top_right=(SCREEN_SIZE, SCREEN_SIZE),
                    key="_Canvas1_"),
           sg.Slider(range=(100, 0), orientation='v', size=(20, 10),
                     enable_events=True, disable_number_display=True,
                     default_value=0, key="_Sl_vertical_"),
           sg.Frame("", [[sg.Frame("Class annotation", [
                [sg.Button('Original', button_color=['green', 'white'])],
                [sg.Button('Class 1', button_color=['white', 'red'])],
                [sg.Button('Class 2', button_color=['white', 'green'])],
                [sg.Button('Class 3', button_color=['white', 'blue'])],
                [sg.Slider(range=(0, 100), orientation='h', size=(10, 10),
                           default_value=20, key="_In_sigmaH_")],
                [sg.Button('Expand', size=(6, 1))], [sg.Button('Fill', size=(6, 1))],
                [sg.Button('Clean', size=(6, 1))], ])],
                ])],
          [sg.Slider(range=(0, 100), orientation='h', size=(40, 10),
                     enable_events=True, disable_number_display=True,
                     default_value=0, key="_Sl_horizontal_")],
          [sg.Text('No file opened', key='_Tx_opened_image_', size=(60,1))],
          [sg.Text('Class 1 selected', key='_Tx_selected_')]
          ]

window = sg.Window('Superpixel Growing Segmentation', layout)
canvas1 = window.Element("_Canvas1_")
temp = np.zeros(canvas1.CanvasSize)

# Global values initialization

y = 0
x = 0
maxDist = 19
active_class = 'class1'
classe = 1
color = [255, 0, 0]
mode = 0  # 0: drag; 1: point; 2: grow; 3: path

click_up = -1
click_down = -1
first_click = []
second_click = []

tempColor = []

# View functions


def updateCanvas(image, hor, ver):
    '''
    Draw a given image in the Canvas given the horizontal and vertical
    position.
    The image is buffered in a binary stream

    Parameters
    ----------
    image : TYPE
        RGB image.
    hor : TYPE
        Initial horizontal position in the image.
    ver : TYPE
        Initial vertical position in the image.

    Returns
    -------
    image : TYPE
        RGB image.

    '''

    # if np.size(np.shape(image)) == 3:
    #     image = cv2.cvtColor(np.uint8(image), cv2.COLOR_BGR2RGB)

    size = canvas1.CanvasSize
    positionX = int(np.shape(image)[1]/100*hor)
    positionY = int(np.shape(image)[0]/100*ver)

    if positionX > np.shape(image)[1]-size[1]:
        positionX = np.shape(image)[1]-size[1]-1
    if positionY > (np.shape(image)[0]-size[0]):
        positionY = np.shape(image)[0]-size[0]-1

    try:
        # Create buffer
        buffered = BytesIO()

        # Save image to buffer
        Image.fromarray(np.uint8(image[positionY:size[0]+positionY,
                                       positionX:size[1]+positionX])
                        ).save(buffered, format="PNG")

        # Encode buffer to binary
        encoded = base64.b64encode(buffered.getvalue())

        # Load encoded image buffer to canvas
        canvas1.DrawImage(data=encoded, location=(0, SCREEN_SIZE))
        canvas1.Update()
    except Exception as e:
        print("Update canvas " + str(e))
    return


def paintSuperpixel(superpixel, target, image=None, index=None,
                    color=[255, 255, 255]):
    '''
    Paint certain pixels according to superpixel index given.

    Parameters
    ----------
    superpixel : TYPE
        Superpixel image with indexes for each pixel.
    target : TYPE
        Image to be painted with specific superpixel.
    image : TYPE, optional
        DESCRIPTION. The default is None.
    index : TYPE, optional
        DESCRIPTION. The default is None.
    color : TYPE, optional
        DESCRIPTION. The default is [255,255,255].

    Returns
    -------
    target : TYPE
        DESCRIPTION.

    '''

    target[:, :, 0] = np.where((superpixel == index), color[0],
                               target[:, :, 0])
    target[:, :, 1] = np.where((superpixel == index), color[1],
                               target[:, :, 1])
    target[:, :, 2] = np.where((superpixel == index), color[2],
                               target[:, :, 2])

    return target


@jit(nopython=True)
def computeSuperpixelColor(labImage, superpixel):
    '''
    Compute the centroid color in a CIELab space for each superpixel.

    Parameters
    ----------
    image : TYPE
        The reference image in CIELab colors.
    superpixel : TYPE
        The superpixel image with the indexes for each pixel.

    Returns
    -------
    superpixelColor : TYPE
        Array of CieLAB colors for each Superpixel.

    '''

    superpixel_f = superpixel.flatten()
    L_values = labImage[:, :, 0].flatten()
    a_values = labImage[:, :, 1].flatten()
    b_values = labImage[:, :, 2].flatten()

    superpixel_max = superpixel.max()+1

    superpixelColor = [(0, 0, 0)]

    for i in range(1, superpixel_max):
        L = np.nanmedian(np.where((superpixel_f == i), L_values, np.nan))
        a = np.nanmedian(np.where((superpixel_f == i), a_values, np.nan))
        b = np.nanmedian(np.where((superpixel_f == i), b_values, np.nan))

        superpixelColor.append((L, a, b))

    return superpixelColor


def superpixels_to_graph(superpixel):

    offset = 1
    neighbors = np.full((superpixel.max()+1, superpixel.max()+1), False)
    for i in range(1, np.shape(superpixel)[0]-2):
        for j in range(1, np.shape(superpixel)[1]-2):
            temp = superpixel[i-offset:i+offset+1,
                              j-offset:j+offset+1].flatten()
            for k in temp:
                if k != superpixel[i, j]:
                    neighbors[superpixel[i, j]][k] = True
                    neighbors[k][superpixel[i, j]] = True

    A = []
    for i in range(0, superpixel.max()):
        temp = neighbors[i:i+1, :]
        A.append(np.unique(np.sort(np.where(temp == True)[1])))

    return A


@jit(nopython=True)
def compute_color_distance(color_0, color_1):

    L0, a0, b0 = color_0
    L1, a1, b1 = color_1

    dist = math.sqrt(math.pow((L1-L0), 2) + math.pow((a1-a0), 2)
                     + math.pow((b1-b0), 2))

    return dist


def compareSuperpixel(superpixelColor, target, tempColor, maxDist):
    '''
    Compare two superpixel colors by computing the distance in a CIELab space.

    Parameters
    ----------
    superpixelColor : TYPE
        List of colors for each superpixel.
    target : TYPE
        Reference superpixel index to be compared.
    tempColor : TYPE
        Reference superpixel index to be compared.
    maxDist : TYPE
        Maximum acceptable distance in the CIELab space.

    Returns
    -------
    bool
        True if the computed distance is under maxDist value. False otherwise.

    '''

    L0, a0, b0 = np.median(tempColor, axis=0)
    L1, a1, b1 = superpixelColor[target]

    dist = compute_color_distance((L0, a0, b0), (L1, a1, b1))

    if dist < maxDist:
        return True
    else:
        return False


def growingSuperpixelBreadth(superpixelColor, neighbors, seed, tempColor,
                             classe, maxDist):
    '''
    Given a target superpixel index the neighbors are analysed if within the
    max color distance. Uses breadth search.

    Parameters
    ----------
    superpixel : TYPE
        Superpixel array with annotated Superpixel for each pixel.
    superpixelColor : TYPE
        List of colors for each superpixel.
    image : TYPE
        RGB image.
    mask : TYPE
        RGB mask image to be drawn.
    neighbors : TYPE
        DESCRIPTION.
    seed : TYPE
        Initial target.
    target : TYPE
        Initial target.
    tempColor : TYPE
        Initial reference color.
    classe : TYPE
        Which class to be painted.
    maxDist : TYPE
        Maximum acceptable distance in the CIELab space.
    canvas : TYPE, optional
        If True forces canvas update. The default is False.

    Returns
    -------
    None.

    '''

    queue = []
    queue.append(seed)
    # visited[seed] = True

    backtrack = []
    backtrack.append(seed)

    while queue:  # queue
        s = queue.pop(0)
        # print("Pop " + str(s))
        temp = neighbors[s]
        for k in temp:
            # if visited[s] == False:
            if compareSuperpixel(superpixelColor, k, tempColor,
                                 maxDist) is True:
                if visited[k] is False or superpixelClass[k] == 0:
                    queue.append(k)
                    # print("Push " + str(k))
                    tempColor = np.insert(tempColor, 0,
                                          superpixelColor[k], 0)
                    tempColor = np.reshape(tempColor,
                                           (int(np.size(tempColor)/3), 3))
                    backtrack.append(k)

                    superpixelClass[k] = classe
            visited[k] = True
        # print(np.size(queue))
        if np.size(queue) > 50:
            # print(queue)
            queue = []
    return backtrack


def superpixel_forest_segmentation(A, seed, I, T):
    # A = neighbors
    # seed = target
    # I = superpixelColor
    # T = maxDist

    visited = []
    unvisited = list(range(np.shape(np.asarray(A))[0]))

    path_cost = np.full((np.size(unvisited), 2), np.inf)

    path_cost[seed, 0] = 0

    while np.size(unvisited) != 0:

        current_vertex = unvisited[np.argmin(path_cost[unvisited, 0])]

        unvisited_neighbour = np.intersect1d(A[current_vertex], unvisited)

        for i in unvisited_neighbour:

            dist = compute_color_distance(I[current_vertex], I[i])

            temp = max(dist, path_cost[current_vertex, 0])

            # if temp < np.inf: print(dist, path_cost[current_vertex, 0], temp)

            # temp = dist + path_cost[current_vertex, 0]

            if temp < T:
                path_cost[i] = temp, current_vertex

        visited.append(current_vertex)
        unvisited.remove(current_vertex)

    backtrack = np.where(path_cost[:, 0] < np.inf)[0]

    return backtrack


# @jit(nopython=True)
def forest_segmentation2(A, seed, end, I, path_cost=None):
    # A = neighbors
    # seed = target
    # I = superpixelColor
    # T = maxDist

    if path_cost is None:
        visited = []
        unvisited = list(range(np.shape(np.asarray(A))[0]))

        path_cost = np.full((np.size(unvisited), 2), np.inf)

        path_cost[seed, 0] = 0

        while np.size(unvisited) != 0:

            current_vertex = unvisited[np.argmin(path_cost[unvisited, 0])]

            unvisited_neighbour = np.intersect1d(A[current_vertex], unvisited)

            for i in unvisited_neighbour:

                dist = compute_color_distance(I[current_vertex], I[i])

                temp = max(dist, path_cost[current_vertex, 0])

                # if temp < np.inf: print(dist, path_cost[current_vertex, 0], temp)

                # temp = dist + path_cost[current_vertex, 0]

                if temp < path_cost[i, 0]:
                    path_cost[i] = temp, current_vertex

            visited.append(current_vertex)
            unvisited.remove(current_vertex)

    backtrack = np.where(path_cost[:, 0] < path_cost[end, 0])[0]

    return backtrack, path_cost


def least_path(neighbors, start, end, superpixelColor):

    visited = []
    unvisited = list(range(np.shape(neighbors)[0]))

    path_cost = np.full((np.size(unvisited), 2), np.inf)

    # start = 0
    path_cost[start, 0] = 0

    while np.size(unvisited) != 0:

        current_vertex = unvisited[np.argmin(path_cost[unvisited, 0])]

        if current_vertex == end:
            break

        unvisited_neighbour = np.intersect1d(
            neighbors[current_vertex], unvisited)

        for i in unvisited_neighbour:
            dist = compute_color_distance(superpixelColor[current_vertex],
                                          superpixelColor[i])
            if dist + path_cost[current_vertex, 0] < path_cost[i, 0]:
                path_cost[i] = (dist +
                                path_cost[current_vertex, 0]), current_vertex

        visited.append(current_vertex)
        unvisited.remove(current_vertex)

    # backtrack
    backtrack = []
    backtrack.append(current_vertex)
    while current_vertex != start:

        current_vertex = np.uint(path_cost[current_vertex][1])
        backtrack.append(current_vertex)

    return backtrack


def showImage(image):
    '''
    Open a image with the OS image viewer

    Parameters
    ----------
    image : TYPE
        Numpy array of a RGB or grayscale image.

    Returns
    -------
    None.

    '''

    pil_img = Image.fromarray(image)
    pil_img.show()

    return

# Controler section


while True:
    event, values = window.Read()

    try:
        hor = int(values["_Sl_horizontal_"])
        ver = int(values["_Sl_vertical_"])
    except Exception as e:
        print(e)

    if event is None or event == 'Exit':
        break
    elif event == 'Open image':  # -------------------------------------------

        address = sg.PopupGetFile('Document to open')
        # address = 'D:/Ademir/Coding/datasets/image1/0055.png'

        try:
            file = open(address, 'rb').read()
            try:
                image = cv2.imdecode(np.frombuffer(file, np.uint8), 1)
                # 0 in the case of grayscale images

                image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

                # image = cv2.bilateralFilter(image, 10, 75, 75)
                # mask = np.copy(image)
                # mask = np.full((np.shape(image)[0], np.shape(image)[1]), 0, dtype=np.uint8)
                mask = np.full((np.shape(image)[0], np.shape(image)[1], 3), 0, dtype=np.uint8)
                original = np.copy(image)
                temp = updateCanvas(image, hor, ver)
                window.Element("_Tx_opened_image_").Update(value="Opened: " +
                                                           address)
                # window.Element("_Bt_Smooth_").Update(disabled=False)

            except ValueError:
                sg.Popup(ValueError)
        except Exception as e:
            sg.Popup(e)

    elif event == 'Open Superpixel':  # --------------------------------------

        address = sg.PopupGetFile('Document to open')

        # address = 'D:/Ademir/Coding/datasets/image1-superpixels2000/0055.png'

        try:
            superpixel = Image.open(address)
            superpixel = np.asarray(superpixel)
            # superpixel = superpixel.transpose()
        except Exception as e:
            sg.Popup(e)

    elif event == 'Generate Superpixels':  # ---------------------------------

        # View popup to receive Superpixel parameters
        sp_layout = [[sg.Text('Insert the number of superpixel desired.')],
                     [sg.Text('Quantity:'), sg.InputText()],
                     [sg.Button('Ok'), sg.Button('Cancel')]]

        sp_window = sg.Window('Slic Superpixels', sp_layout)

        while True:
            sp_event, sp_values = sp_window.read()
            if sp_event in (None, 'Cancel'):
                break
            if sp_event == 'Ok':
                try:
                    del(neighbors)
                    del(superpixelColors)
                    del(superpixelClass)
                    del(visited)
                except Exception:
                    print('No data to clean')
                break
        sp_window.close()

        try:
            superpixel = slic(image, n_segments=int(sp_values[0]),
                              compactness=40)
        except Exception as e:
            print(e)

    #  Change modes------------------------------------------------------------
    elif event == 'drag':
        mode = 0
    elif event == 'brush':
        mode = 1
    elif event == 'grow':
        mode = 2
    elif event == 'path':
        mode = 3
    elif event == 'dynamic':
        mode = 4
    elif event == 'forest':
        mode = 5

    #  Change canvas image and colors------------------------------------------
    elif event == 'Class 1':
        active_class = 'class1'
        color = [255, 0, 0]
        temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
        updateCanvas(temp, hor, ver)
        window.Element("_Tx_selected_").Update(value='Class 1 selected')
    elif event == 'Class 2':
        active_class = 'class2'
        color = [0, 255, 0]
        temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
        updateCanvas(temp, hor, ver)
        window.Element("_Tx_selected_").Update(value='Class 2 selected')
    elif event == 'Class 3':
        active_class = 'class3'
        color = [0, 0, 255]
        temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
        updateCanvas(temp, hor, ver)
        window.Element("_Tx_selected_").Update(value='Class 3 selected')
    elif event == 'Original':
        try:
            updateCanvas(original, hor, ver)
        except Exception as e:
            print(e)

    elif event == 'Load CSV file':  # ----------------------------------------

        try:
            maxDist = float(values["_In_sigmaH_"])
        except Exception as e:
            print(e)

        address = sg.PopupGetFile('Document to open')

        if address is not None:
            neighbors = superpixels_to_graph(superpixel)
            labImage = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)
            superpixelColor = computeSuperpixelColor(labImage, superpixel)
            superpixelClass = np.zeros((superpixel.max()+1))
            visited = np.full((superpixel.max()+1), False)

            mask = np.copy(image)
            with open(address) as csv_file:
                csv_reader = csv.reader(csv_file, delimiter=';', )
                line_count = 0
                seed_image = np.copy(image)
                for row in csv_reader:
                    if line_count != 0:
                        # image[1,2] = red
                        # image[int(row[1])-1, int(row[0])-1] = (255, 0, 0)
                        seed_image = cv2.circle(seed_image,
                                                (int(row[1])-1,
                                                 int(row[0])-1), 5,
                                                (255, 0, 0), 0)
                        target = superpixel[int(row[0])-1, int(row[1])-1]
                        tempColor = superpixelColor[target]
                        tempColor = np.reshape(tempColor, (int(np.size(
                                                           tempColor)/3), 3))

                        backtrack = growingSuperpixelBreadth(superpixelColor,
                                                             neighbors, target,
                                                             tempColor,
                                                             classe, maxDist)
                        for target in backtrack:
                            mask = paintSuperpixel(superpixel, mask, image,
                                                   target, color)

                        temp = updateCanvas(mask, hor, ver)
                        # pontos.append([int(row[1]),int(row[0])])
                        # image = cv2.circle(image, (SCREEN_SIZE,SCREEN_SIZE),
                        #                    10, red, 3)
                        line_count = line_count + 1
                    line_count = line_count + 1
                cv2.imwrite(address+".png",
                            cv2.cvtColor(seed_image, cv2.cv2.COLOR_BGR2RGB))

    elif event == 'Save mask':  # --------------------------------------------

        save_layout = [[
            sg.InputText(visible=True, enable_events=True, key='fig_path',
                         size=(10, 50)),
            sg.FileSaveAs(
                key='fig_save',
                file_types=(('PNG', '.png'), ('JPG', '.jpg')),
            ), sg.OK()
        ]]
        save_window = sg.Window('Demo Application', save_layout, finalize=True)

        while True:  # Event Loop
            save_event, save_values = save_window.Read()
            print(save_event)
            if (save_event == 'fig_path') and (save_values['fig_path'] != ''):
                save_address = save_values['fig_path']
                save_window.Close()
            if save_event is None or save_event == "OK":
                break

        save_window.Close()

        if save_address is not None:
            try:
                cv2.imwrite(save_address, cv2.cvtColor(mask, cv2.COLOR_RGB2BGR))
            except Exception:
                print("Impossible to save")

    elif event == '_Sl_horizontal_' or event == '_Sl_vertical_':
        temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
        updateCanvas(temp, hor, ver)
        # temp = updateCanvas(temp, hor, ver)

    elif event == 'Expand':  # ------------------------------------------

        try:
            maxDist = float(values["_In_sigmaH_"])
        except Exception as e:
            print(e)

        visited = np.full((superpixel.max()+1), False)

        try:
            np.shape(neighbors)
            np.shape(superpixelColor)
        except Exception:
            neighbors = superpixels_to_graph(superpixel)
            labImage = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)
            superpixelColor = computeSuperpixelColor(labImage, superpixel)
            superpixelClass = np.zeros((superpixel.max()+1))
            visited = np.full((superpixel.max()+1), False)

        try:
            tempColor = superpixelColor[superpixel[y, x]]
            tempColor = np.reshape(tempColor, (int(np.size(tempColor)/3), 3))

            target = superpixel[y, x]

            # Superpixel Region Growing
            # backtrack = growingSuperpixelBreadth(superpixelColor,
            #                                      neighbors, target,
            #                                      tempColor,
            #                                      classe, maxDist)

            # Superpixel Forest Segmentation
            start_time = time.time()
            backtrack = superpixel_forest_segmentation(neighbors, target,
                                                       superpixelColor,
                                                       maxDist)
            end_time = time.time()
            print('Time: ' + str((end_time - start_time)))

            for target in backtrack:
                mask = paintSuperpixel(superpixel, mask, image,
                                       target, color)
            temp = updateCanvas(mask, hor, ver)
        except Exception as e:
            print(e)

    elif event == 'Fill':  # -------------------------------------------------

        if active_class == 'class1':
            mask[np.where(np.all(mask == [0, 0, 0], axis=-1))] = [255, 0, 0]

        if active_class == 'class2':
            mask[np.where(np.all(mask == [0, 0, 0], axis=-1))] = [0, 255, 0]

        if active_class == 'class3':
            mask[np.where(np.all(mask == [0, 0, 0], axis=-1))] = [0, 0, 255]

        temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
        updateCanvas(temp, hor, ver)

    elif event == 'Clean':  # ------------------------------------------------
        superpixelClass = np.zeros((superpixel.max()+1))
        visited = np.full((superpixel.max()+1), False)
        
        # mask[np.where((superpixel == superpixel[y, x]))] = color

        if active_class == 'class1':
            mask[np.where(np.all(mask == [255, 0, 0], axis=-1))] = [0, 0, 0]

        if active_class == 'class2':
            mask[np.where(np.all(mask == [0, 255, 0], axis=-1))] = [0, 0, 0]

        if active_class == 'class3':
            mask[np.where(np.all(mask == [0, 0, 255], axis=-1))] = [0, 0, 0]

        temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
        updateCanvas(temp, hor, ver)

    elif event == 'process':  # -----------------------------------------------
        try:
            neighbors = superpixels_to_graph(superpixel)
            labImage = cv2.cvtColor(image, cv2.COLOR_BGR2Lab)
            superpixelColor = computeSuperpixelColor(labImage, superpixel)
            superpixelClass = np.zeros((superpixel.max()+1))
            visited = np.full((superpixel.max()+1), False)
            #mask = np.copy(image)
        except Exception as e:
            print(e)

    elif event == '_Canvas1_':  # --------------------------------------------
        position = values['_Canvas1_']

        try:
            maxDist = float(values["_In_sigmaH_"])
            size = canvas1.CanvasSize
            positionX = int(np.shape(image)[1]/100*hor)
            positionY = int(np.shape(image)[0]/100*ver)

            if positionX > np.shape(image)[1]-size[1]:
                positionX = np.shape(image)[1]-size[1]-1
            if positionY > (np.shape(image)[0]-size[0]):
                positionY = np.shape(image)[0]-size[0]-1

            x = positionX+position[0]
            y = positionY+abs(position[1]-size[1])
        except Exception as e:
            print("Canvas error" + e)

        visited = np.full((superpixel.max()+1), False)

        try:
            if mode == 1:  # Paint individual superpixel
                # mask = np.full((np.shape(image)[0], np.shape(image)[1]), 0, dtype=np.uint8)
                # mask = np.full((np.shape(image)[0], np.shape(image)[1], 3), 0, dtype=np.uint8)
                # mask = np.where((superpixel == superpixel[y, x]), 255, mask)

                mask[np.where((superpixel == superpixel[y, x]))] = color
                temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                # mask = paintSuperpixel(superpixel, mask, image,
                #                        superpixel[y, x], color)
                updateCanvas(temp, hor, ver)

            if mode == 2:  # Superpixel region growing segmentation
                try:
                    tempColor = superpixelColor[superpixel[y, x]]
                    tempColor = np.reshape(tempColor, (
                        int(np.size(tempColor)/3), 3))

                    start_time = time.time()
                    target = superpixel[y, x]
                    backtrack = []
                    backtrack = growingSuperpixelBreadth(superpixelColor,
                                                         neighbors, target,
                                                         tempColor,
                                                         classe, maxDist)
                    end_time = time.time()
                    print('Region growing time: ' + str((end_time - start_time)))

                    for target in backtrack:
                        # mask = paintSuperpixel(superpixel, mask, image, target,
                        #                        color)

                        mask[np.where((superpixel == target))] = color

                    temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                    updateCanvas(temp, hor, ver)
                    # temp = updateCanvas(mask, hor, ver)
                except Exception as e:
                    print(e)

            if mode == 4:  # Dynamic forest segmentation - click down
                click_down += 1
                aux_click = []
                if click_down == 0:
                    first_click = [y, x]
                    if 'path_cost' not in globals():
                        path_cost = None
                else:
                    second_click = [y, x]

                if first_click != second_click and second_click != aux_click:

                    start = superpixel[first_click[0], first_click[1]]
                    end = superpixel[second_click[0], second_click[1]]

                    backtrack, path_cost = forest_segmentation2(neighbors, start, end, superpixelColor, path_cost)
                    aux_click = second_click

                    mask = np.copy(image)

                    for target in backtrack:
                        mask[np.where((superpixel == target))] = color

                    temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                    updateCanvas(temp, hor, ver)

            if mode == 5:  # Superpixel region growing segmentation
                tempColor = superpixelColor[superpixel[y, x]]
                tempColor = np.reshape(tempColor, (int(np.size(tempColor)/3), 3))

                target = superpixel[y, x]

                start_time = time.time()
                backtrack = superpixel_forest_segmentation(neighbors, target,
                                                           superpixelColor,
                                                           maxDist)
                end_time = time.time()
                print('Time: ' + str((end_time - start_time)))

                for target in backtrack:
                    # mask = paintSuperpixel(superpixel, mask, image,
                    #                        target, color)
                    mask[np.where((superpixel == target))] = color

                temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                updateCanvas(temp, hor, ver)
                # temp = updateCanvas(mask, hor, ver)

        except Exception as e:
            print(e)

    elif event == "_Canvas1_+UP":  # -----------------------------------------
        try:
            size = canvas1.CanvasSize
            positionX = int(np.shape(image)[1]/100*hor)
            positionY = int(np.shape(image)[0]/100*ver)

            if positionX > np.shape(image)[1]-size[1]:
                positionX = np.shape(image)[1]-size[1]-1
            if positionY > (np.shape(image)[0]-size[0]):
                positionY = np.shape(image)[0]-size[0]-1

            x = positionX+position[0]
            y = positionY+abs(position[1]-size[1])
            print(x, y)

            if mode == 3:  # Least path drawing
                click_up += 1
                if click_up == 0:
                    first_click = [y, x]

                    mask[np.where((superpixel == superpixel[y, x]))] = color
                    temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                    updateCanvas(temp, hor, ver)
                elif click_up == 1:
                    second_click = [y, x]

                    start = superpixel[first_click[0], first_click[1]]
                    end = superpixel[second_click[0], second_click[1]]

                    start_time = time.time()
                    backtrack = least_path(neighbors, start, end,
                                           superpixelColor)
                    end_time = time.time()
                    print('Least path processing time: ' + str((end_time - start_time)))

                    start_time = time.time()
                    for target in backtrack:
                        # mask = paintSuperpixel(superpixel, mask, image, target,
                        #                        color)
                        mask[np.where((superpixel == target))] = color

                    temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                    updateCanvas(temp, hor, ver)

                    # temp = updateCanvas(mask, hor, ver)
                    end_time = time.time()
                    print('Screen update time: ' + str((end_time - start_time)))
                    click_up = -1

            if mode == 4:  # Dynamic forest segmentation - click up
                click_up += 1
                if click_up == 0:
                    second_click = [y, x]

                    start = superpixel[first_click[0], first_click[1]]
                    end = superpixel[second_click[0], second_click[1]]

                    start_time = time.time()

                    backtrack, path_cost = forest_segmentation2(neighbors, start, end, superpixelColor, path_cost)
                    end_time = time.time()
                    print('Dynamic forest time: ' + str((end_time - start_time)))

                    for target in backtrack:
                        # mask = paintSuperpixel(superpixel, mask, image, target,
                        #                        color)
                        mask[np.where((superpixel == target))] = color
                        
                    temp = cv2.addWeighted(image, 1, mask, 1, 0.0)
                    updateCanvas(temp, hor, ver)

                    # temp = updateCanvas(mask, hor, ver)

                    del(path_cost)
                    del(first_click)
                    del(second_click)
                    aux_click = []
                    click_up = -1
                    click_down = -1

        except Exception as e:
            print(e)

    # print(event, values)

window.Close()
